﻿

namespace HDJ.Framework.Core.FixedPointy
{
   public struct FixVector2
    {
        public static readonly FixVector2 Zero = new FixVector2(Fix64.Zero, Fix64.Zero);
        public static readonly FixVector2 One = new FixVector2(Fix64.One, Fix64.One);
        public static readonly FixVector2 UnitX = new FixVector2(Fix64.One, Fix64.Zero);
        public static readonly FixVector2 UnitY = new FixVector2(Fix64.Zero, Fix64.One);

        public Fix64 x;
        public Fix64 y;

        public FixVector2(Fix64 x, Fix64 y)
        {
            this.x = x;
            this.y = y;
        }
        public FixVector2(long x, long y)
        {
            this.x = (Fix64)x;
            this.y = (Fix64)y;
        }
        public FixVector2(int x, int y)
        {
            this.x = new Fix64(x);
            this.y = new Fix64(y);
        }
        public FixVector2(float x, float y)
        {
            this.x = new Fix64(x);
            this.y = new Fix64(y);
        }
        public FixVector2(double x, double y)
        {
            this.x = new Fix64(x);
            this.y = new Fix64(y);
        }
        public FixVector2(decimal x, decimal y)
        {
            this.x = new Fix64(x);
            this.y = new Fix64(y);
        }


        public static FixVector2 operator +(FixVector2 rhs)
        {
            return rhs;
        }
        public static FixVector2 operator -(FixVector2 rhs)
        {
            return new FixVector2(-rhs.x, -rhs.y);
        }

        public static FixVector2 operator +(FixVector2 lhs, FixVector2 rhs)
        {
            return new FixVector2(lhs.x + rhs.x, lhs.y + rhs.y);
        }
        public static FixVector2 operator -(FixVector2 lhs, FixVector2 rhs)
        {
            return new FixVector2(lhs.x - rhs.x, lhs.y - rhs.y);
        }

        public static FixVector2 operator +(FixVector2 lhs, Fix64 rhs)
        {
            return lhs.ScalarAdd(rhs);
        }
        public static FixVector2 operator +(Fix64 lhs, FixVector2 rhs)
        {
            return rhs.ScalarAdd(lhs);
        }
        public static FixVector2 operator -(FixVector2 lhs, Fix64 rhs)
        {
            return new FixVector2(lhs.x - rhs, lhs.y - rhs);
        }
        public static FixVector2 operator *(FixVector2 lhs, Fix64 rhs)
        {
            return lhs.ScalarMultiply(rhs);
        }
        public static FixVector2 operator *(Fix64 lhs, FixVector2 rhs)
        {
            return rhs.ScalarMultiply(lhs);
        }
        public static FixVector2 operator /(FixVector2 lhs, Fix64 rhs)
        {
            return new FixVector2(lhs.x / rhs, lhs.y / rhs);
        }

       
        public Fix64 Dot(FixVector2 rhs)
        {
            return x * rhs.x + y * rhs.y;
        }

        public Fix64 Cross(FixVector2 rhs)
        {
            return x * rhs.y - y * rhs.x;
        }

        FixVector2 ScalarAdd(Fix64 value)
        {
            return new FixVector2(x + value, y + value);
        }
        FixVector2 ScalarMultiply(Fix64 value)
        {
            return new FixVector2(x * value, y * value);
        }

        public Fix64 Magnitude()
        {
            Fix64 N = x * x + y * y;
            if (N == Fix64.Zero)
                return  Fix64.Zero;

            return Fix64.Sqrt(N);
        }

        public FixVector2 Normalize()
        {
            if (x == Fix64.Zero && y == Fix64.Zero)
                return FixVector2.Zero;

            var m = Magnitude();
            return new FixVector2(x / m, y / m);
        }

        public override string ToString()
        {
            return string.Format("({0}, {1})", x, y);
        }
    }
}
